DTLS : Datagram TLS communication

更新时间:
2024-05-13
下载文档

DTLS : Datagram TLS communication

Dtls is an encrypted communication module that provides Datagram TLS communication support. This module is similar with Tls module but used UDP as the transport layer protocol.

Like the Tls module, the JSRE Dtls module also supports multitasking mode.

User can use the following code to import the Dtls module.

var Dtls = require('dtls');

Support

The following shows Dtls module APIs available for each permissions.

 User ModePrivilege Mode
Dtls.createServer
Dtls.createClient
Dtls.createByFd
dtls.sockFd
dtls.addcert
dtls.accept
dtls.send
dtls.recv
dtls.pending
dtls.error
dtls.close
dtls.flyAway
dtls.sockName
dtls.peerName
dtls.bindToDevice
dtls.setTTL
dtls.setIPv6Only
dtls.getRecvBufferSize
dtls.getSendBufferSize
dtls.setRecvBufferSize
dtls.setSendBufferSize

Dtls Class

Dtls.createServer(opt, sockaddr)

  • opt {Object} Dtls server option.
  • sockaddr {Object} Local address.
  • Returns: {Object} Dtls object.

opt includes following items:

  • name {String} Server name for multitasking. If it is a single task server, this can be undefined.
  • ca {String} . default: no CA certificates.
  • cert {String} Server certificate.
  • key {String} Private key of server certificate.
  • passwd {String} Private key password. default: no password.
  • ipcert {Boolean} If the client does not send the SNI option, whether to find the corresponding IP signature certificate. default: false.
  • renegotiate {Boolean} If this server support renegotiate. default: false.
  • handshakeTimeout {Integer} TLS handshake maximum timeout (2000 ~ 120000). default: 60000.

sockaddr includes following items:

  • domain {Integer} Address domain: socket.AF_INET or socket.AF_INET6.
  • addr {String} Address.
  • port {Integer} Port.

Create a Datagram TLS server and bind to the specified address.

EdgerOS 1.6.5 and later versions, domain can use Dtls.AF_INET and Dtls.AF_INET6; EdgerOS 1.10.1 and later versions, The domain member can be omitted.

Example

var option = {
  name: 'Dtls-Server1',
  cert: fs.readString('./cert.pem'),
  key: fs.readString('./cert.key')
};

var saddr = Dtls.sockaddr(Dtls.INADDR_ANY, 3000);
var dtls = Dtls.createServer(option, saddr);

var option = {
  name: 'Dtls-Server1-v6',
  cert: fs.readString('./cert.pem')
  key: fs.readString('./cert.key')
};

var saddr6 = Dtls.sockaddr6(Dtls.IN6ADDR_ANY, 3001);
var dtls6 = Dtls.createServer(option, saddr6);

Dtls.createClient(opt, sockaddr[, timeout])

  • opt {Object} Dtls client option.
  • timeout {Integer} Wait timeout in milliseconds. default: undefined means timeout with default connect timeout setting.
  • Returns: {Object} Dtls object.

opt includes following items:

  • rejectUnauthorized {Boolean} Whether the server certificate should be verified against the list of supplied CAs. default: false.
  • loadDefaultCerts {Boolean} Whether to load JSRE / EdgerOS environment default trusted certificates. default: false.
  • ca {String} Trusted CA certificates chain. default: undefined.
  • server {String} Set the server host name (usually is the server host name) to check against the received server certificate. default: undefined.
  • renegotiate {Boolean} If this client support renegotiate. default: false.
  • handshakeTimeout {Integer} TLS handshake maximum timeout (2000 ~ 120000). default: 60000.

If you need authentication between the server and the client, you can specify the client certificate and private key through the following members of opt:

  • cert {String} Client certificate.
  • key {String} Private key of client certificate.
  • passwd {String} Private key password. default: no password.

Create a Datagram TLS client and connects to the specified remote host. Use synchronous mode.

Example

var option = {
  rejectUnauthorized: false,
  ca: fs.readString('./ca.pem')
};

var saddr = Dtls.sockaddr('192.168.0.3', 2049);
var dtls = Dtls.createClient(option, saddr);
if (!dtls) {
  console.log('connect error:', sys.error());
}

Dtls.createClient(opt, sockaddr, callback)

  • opt {Object} Dtls client option.
  • sockaddr {Object} Remote address.
  • callback {Function} Dtls connected (udp handshake) callback.
    • dtls {Object} Dtls object.
    • remote {Object} Remote address. EdgerOS 1.6.5 and later versions add this argument.
  • Returns: {Object} Dtls object.

Create a Datagram TLS client and connects to the specified remote host. Use asynchronous mode.

Example

var option = {
  rejectUnauthorized: false,
  loadDefaultCerts: true
};

var saddr = Dtls.sockaddr('192.168.0.3', 3000);
var dtls = Dtls.createClient(option, saddr, (dtls) => {
  console.log('Connected');
});

while (true) {
  iosched.poll(); // callback() will called here.
}

Dtls.createByFd(name, sockFd[, timeout])

  • name {String} Server name for multitasking.
  • sockFd {Integer} Socket file descriptor, MUST udp socket descriptor.
  • timeout {Integer} Wait timeout in milliseconds. default: undefined means timeout with default handshake timeout setting.
  • Returns: {Object} Dtls object.

Create a dtls object with socket file descriptor, mainly used to multitasking Datagram TLS server. Use synchronous mode.

Example

var dtls = Dtls.createByFd('Dtls-Server1', sockFd);

Dtls.createByFd(name, sockFd, callback)

  • name {String} Server name for multitasking.
  • sockFd {Integer} Socket file descriptor, MUST udp socket descriptor.
  • callback {Function} Handshaked callback.
    • dtls {Object} Dtls object.
  • Returns: {Object} Dtls object.

Create a dtls object with socket file descriptor, mainly used to multitasking Datagram TLS server. Use asynchronous mode.

Example

var dtls = Dtls.createByFd('Dtls-Server1', sockFd, (dtls) => {
  console.log('Client handshaked!');
});

while (true) {
  iosched.poll(); // callback() will called here.
}

Dtls Object

dtls.sockFd

  • {Integer}

The dtls object socket file descriptor. Only for iosched readable event detection in current tasks.

dtls.accept([remoteAddr[, timeout]])

  • remoteAddr {Object} Remote connector address. default: undefined (does not care).
  • timeout {Integer} Wait timeout in milliseconds. default: undefined means wait forever.
  • Returns: {Object} Dtls object.

The Dtls.accept() function shall extract the first connection on the queue of dtls pending connections, pass the current dtls.sockFd to new dtls object and create a new udp socket as a server sockFd. Use synchronous mode.

Example

var remoteAddr = {};
var dtlsNew = dtls.accept(remoteAddr);
if (dtlsNew) {
  console.log('New remote connected:', remoteAddr);
}

dtls.addcert(opt)

  • opt {Object} Dtls server option.
  • Returns: {Boolean} Whether it was added successfully.

opt includes following items:

  • name {String} Server host name.
  • ca {String} Optional trusted CA certificates. default: no CA certificates.
  • cert {String} Server certificate.
  • key {String} Private key of server certificate.
  • passwd {String} Private key password. default: no password.

This method adds a SNI (Server Name Indication) certificate to the tls server. SNI is an extension used to improve SSL or TLS for servers. It mainly solves the disadvantage that one server can only use one certificate (one host name). With the support of the server for virtual hosts, one server can provide services for multiple host names, so SNI must be supported to meet the demand.

Example

dtls.addcert({
  name: 'demo.mysite.com',
  cert: fs.readString('./cert.crt'),
  key: fs.readString('./cert.key')
});

dtls.accept(unused, callback)

  • unused {Undefined} Asynchronous mode does not use this argument.
  • callback {Function} Remote connected callback.
    • dtls {Object} New Dtls object.
    • remoteAddr {Object} Remote address.

The dtls.accept() function shall extract the first connection on the queue of tls pending connections, and create a new dtls object. Use asynchronous mode.

Example

dtls.accept(undefined, (newDtls, remoteAddr) => {
  console.log('New remote connected:', remoteAddr);
});

while (true) {
  iosched.poll(); // callback() will called here.
}

dtls.send(string[, timeout])

  • string {String} String to be send.
  • timeout {Integer} Wait timeout in milliseconds. default: undefined means wait forever.
  • Returns: {Integer} The number of bytes actually sent, negative error.

The dtls.send() function shall initiate transmission of a message from the specified socket to its peer.

Example

var num = dtls.send('Hello Packet!');
if (num < 0) {
  console.log('send error:', sys.error());
}

dtls.send(buffer[, offset[, length[, timeout]]])

  • buffer {Buffer} Write data buffer.
  • offset {Integer} Buffer offset. default:0.
  • length {Integer} Write length. default:buffer.length.
  • timeout {Integer} Wait timeout in milliseconds. default: undefined means wait forever.
  • Returns: {Integer} The number of bytes actually sent, negative error.

The dtls.send() function shall initiate transmission of a message from the specified socket to its peer.

Example

var buf = new Buffer([1, 2, 3]);

var num = dtls.send(buf);
if (num < 0) {
  console.log('send error:', sys.error());
}

dtls.recv(buffer[, offset[, length[, timeout]]])

  • buffer {Buffer} Receive buffer.
  • offset {Integer} Buffer offset. default:0.
  • length {Integer} Receive length limit. default:buffer.length.
  • timeout {Integer} Wait timeout in milliseconds. default: undefined means wait forever.
  • Returns: {Integer} The number of bytes actually receive, negative error.

The dtls.recv() function shall receive a message from a connection-mode socket.

Example

var buf = new Buffer(1024);

var num = dtls.recv(buf);
if (num < 0) {
  console.log('recv error:', sys.error());
}

dtls.pending()

  • Returns: {Integer} The number of bytes in dtls buffer.

Get the number of readable bytes in the dtls buffer.

Example

var num = dtls.pending();
if (num > 0) {
  dtls.recv(buf);
}

dtls.error()

  • Returns: {Integer} Last socket errno.

Get socket error status and clears it (set to zero). most like (C language):

getsockopt(sockFd, SOL_SOCKET, SO_ERROR, (void *)&err, &len);

Example

var errno = dtls.error();
if (errno) {
  console.log('socket error:', sys.error(errno));
}

dtls.close()

Close dtls connect.

dtls.flyAway()

This function is only used in multitasking mode. Clear the object internal file descriptor and do not recycle the file descriptor. This method is used for file descriptor delivery between multitasking, to prevent system errors from reclaiming file descriptors.

Example

  • main.js
var newDtls = dtls.accept();

// Send file descriptor to other task.
Task.send(otherTask.id(), { sockFd: newDtls.sockFd });

// MUST Call flyAway() and cannot use this object again.
newDtls.flyAway();
  • task.js
var msg = Task.recv();

// Create a dtls object by sockFd.
var dtls = Dtls.createByFd('ServerName', msg.sockFd);

dtls.sockName()

  • Returns: {Object} Local sockaddr.

The dtls.sockName() function shall retrieve the locally-bound name of the specified socket.

Example

var saddr = dtls.sockName();
console.log(saddr);

dtls.peerName()

  • Returns: {Object} Remote sockaddr.

The dtls.peerName() function shall retrieve the peer address of the specified socket.

Example

var saddr = dtls.peerName();
console.log(saddr);

dtls.bindToDevice([ifname])

  • ifname {String} Network interface name. default: all network interface.
  • Returns: {Boolean} Whether the operation was successful.

The dtls.bindToDevice() function binds the network sending and receiving to the specified network interface, and the data packet is only allowed to be sent and received using this network interface.

Example

dtls.bindToDevice('en1');

dtls.setTTL(timeToLive)

  • timeToLive {Integer} IP TTL: 0 ~ 255.
  • Returns: {Boolean} Whether the operation was successful.

Changes the specified udp TTL value of the IP header.

Example

dtls.setTTL(64);

dtls.setIPv6Only(enable)

  • enable {Boolean} Whether to only enable IPv6.
  • Returns: {Boolean} Whether the operation was successful.

If this flag is set to true, then the dtls is re‐stricted to sending and receiving IPv6 packets only.

Example

dtls.setIPv6Only(false);

dtls.getRecvBufferSize()

  • Returns: {Integer} Receive buffer size, negative on error.

Get current receive buffer size in bytes.

dtls.getSendBufferSize()

  • Returns: {Integer} Send buffer size, negative on error.

Get current send buffer size in bytes.

dtls.setRecvBufferSize(size)

  • size {Integer} Receive buffer size. Must be between 1024bytes and 16Mbytes.
  • Returns: {Boolean} Whether the operation was successful.

Set current receive buffer size in bytes.

dtls.setSendBufferSize(size)

  • size {Integer} Send buffer size. Must be between 1024bytes and 16Mbytes.
  • Returns: {Boolean} Whether the operation was successful.

Set current send buffer size in bytes.

Synchronous to asynchronous

JSRE provides a synchronous multitasking model. Like other language environments, it also provides an asynchronous processing model. You can choose any way to develop application, even in one application, depending on the characteristics of the different transactions, you can using different methods at one application.

If you are very familiar with asynchronous development, the following method here can convert synchronization to asynchronous.

Server

Example

var EventEmitter = require('events');
var Dtls = require('dtls');
var fs = require('fs');
var iosched = require('iosched');

var option = {
  cert: fs.readString('./cert.pem')
};

var saddr = Dtls.sockaddr(Dtls.INADDR_ANY, 2049);
var server = Dtls.createServer(option, saddr);

function onMessage(client, buffer, num) {
  console.log('Client:', client.peerName().addr, 'Say:', buffer.toString(num));
}

server.accept(undefined, (client, remoteAddr) => {
  console.log('New client:', remoteAddr);
  EventEmitter.inherits(client);
  client.on('message', onMessage);
  client.revent = iosched.event(iosched.READ, client.sockFd,
  (client) => {
    var buffer = new Buffer(4096);
    var ret = true;
    do {
      var num = client.recv(buffer, 0, buffer.length, 0);
      if (num > 0) {
      client.emit('message', client, buffer, num);
      } else if (num < 0) {
      ret = false;
      console.log('Client lost:', client.peerName());
      client.close();
      }
    } while (num > 0);
    return ret;
  }, undefined, client);
  iosched.add(client.revent);
});

while (true) {
  iosched.poll();
}

Client

Example

var EventEmitter = require('events');
var Dtls = require('dtls');
var fs = require('fs');
var iosched = require('iosched');

var option = {
  rejectUnauthorized: false,
  ca: fs.readString('./ca.pem')
};

var saddr = Dtls.sockaddr('192.168.0.2', 2049);
var client = Dtls.createClient(option, saddr, (client) => {
  client.send('Hello I am client ^_^');
  client.send('Goodbye!');
  client.close();
});

while (true) {
  iosched.poll();
}

Multi-Task Server

Example

  • main.js
var Dtls = require('dtls');
var fs = require('fs');
var iosched = require('iosched');

// Two Task Server.
var next = 0;
var task = [];
task[0] = new Task('./task.js');
task[1] = new Task('./task.js');

var option = {
  name: 'DTLS-Server1',
  cert: fs.readString('./cert.pem')
};

var saddr = Dtls.sockaddr(Dtls.INADDR_ANY, 2049);
var server = Dtls.createServer(option, saddr);

server.accept(undefined, (client, remoteAddr) => {
  console.log('New client:', remoteAddr);
  // The file descriptor is passed to other tasks and will be closed by other tasks.
  task[next].send({ sockFd: client.sockFd });
  // MUST Call flyAway()
  client.flyAway();
  if (++next > 1) {
    next = 0;
  }
});

while (true) {
  iosched.poll();
}
  • task.js
var Dtls = require('dtls');
var socket = require('socket');
var iosched = require('iosched');

function onMessage(client, buffer, num) {
  console.log('Client:', client.peerName().addr, 'Say:', buffer.toString(num));
}

Task.on('message', function(msg, from) {
  if (!msg && msg.sockFd < 0) {
    return;
  }
  var client = Dtls.createByFd('DTLS-Server1', msg.sockFd, 500); // handshake timeout: 500ms
  if (!client) {
    return true; // handshake error.
  }
  EventEmitter.inherits(client);
  client.on('message', onMessage);
  client.revent = iosched.event(iosched.READ, client.sockFd,
  (client) => {
    var buffer = new Buffer(4096);
    var ret = true;
    do {
      var num = client.recv(buffer, 0, buffer.length, 0);
      if (num > 0) {
        client.emit('message', client, buffer, num);
      } else if (num < 0) {
        ret = false;
        console.log('Client lost:', client.peerName());
        client.close();
      }
    } while (num > 0);
    return ret;
  }, undefined, client);
  iosched.add(client.revent);
});

iosched.forever();

In task.js, dtls.createByFd() has a blocking handshake. Can it be transformed into a full asynchronous non-blocking mode?

Dtls Module Constant

Dtls.AF_INET

  • {Integer} 2

Dtls.AF_INET6

  • {Integer} 10

Dtls.INADDR_NONE

  • {String} '255.255.255.255'

Dtls.INADDR_LOOPBACK

  • {String} '127.0.0.1'

Dtls.INADDR_ANY

  • {String} '0.0.0.0'

Dtls.INADDR_BROADCAST

  • {String} '255.255.255.255'

Dtls.IN6ADDR_ANY

  • {String} '::'

Dtls.IN6ADDR_LOOPBACK

  • {String} '::1'

Dtls.IN6ADDR_NODELOCAL_ALLNODES

  • {String} 'ff01::1'

Dtls.IN6ADDR_LINKLOCAL_ALLNODES

  • {String} 'ff02::1'

Dtls.IN6ADDR_LINKLOCAL_ALLROUTERS

  • {String} 'ff01::2'
文档内容是否对您有所帮助?
有帮助
没帮助